<template>
	<div class="real-video-devices-tree">
		<vue-scroll>
			<div style="width: 100%; height: 100%; margin-top: 16px">
				<a-tree
					v-if="treeData?.length"
					v-model:selected-keys="selectedKeys"
					:expanded-keys="cExpandedKeys"
					:auto-expand-parent="autoExpandParent"
					:tree-data="treeData"
					:field-names="{ title: 'name', key: 'id' }"
					@expand="OnExpand"
					@select="Select"
				>
					<template #switcherIcon="{ name, type, id, children, disabled, level }">
						<div v-if="type === 1" class="title title-top" :style="{ paddingLeft: `${8 * (level - 1)}px`, paddingRight: '8px' }">
							<div>
								<span style="margin-right: 5px; color: #8b949e">
									<caret-down-outlined v-if="expandedKeys.includes(id)"></caret-down-outlined>
									<caret-right-outlined v-else></caret-right-outlined>
								</span>

								<span v-if="name.indexOf(searchValue) > -1">
									{{ name.substr(0, name.indexOf(searchValue)) }}

									<span class="font-14-bold inquire-font">{{ searchValue }}</span>
									{{ name.substr(name.indexOf(searchValue) + searchValue.length) }}
								</span>
								<!-- 普通树节点 -->
								<span v-else>{{ name }}</span>
							</div>
							<!-- 在线个数/全部 -->
							<div class="device-num">({{ cDeviceOnline(children) }}/{{ cDeviceTotal(children) }})</div>
						</div>
					</template>
					<template #title="{ name, children, id, level, type, disabled, status }">
						<div
							v-if="type === 0 || !children"
							v-tooltip="name"
							:style="{ paddingLeft: `${5 * (level - 1)}px`, paddingRight: '8px' }"
							:class="[
								'title',
								type === 0 ? 'device-title' : '',
								{ 'device-title--offline': props.offlineCanCheck && status === 0 },
								videoPlays.includes(id) ? 'device-title-active' : ''
							]"
						>
							<!-- 摄像头图标 -->
							<img
								v-if="type === 0 && !disabled && status !== 0"
								src="@/global-assets/svgs/camera-icon.svg"
								alt=""
								style="margin-left: 12px"
							/>
							<img v-if="type === 0 && disabled" src="@/global-assets/svgs/camera-disable.svg" alt="" style="margin-left: 12px" />
							<img
								v-if="props.offlineCanCheck && status === 0"
								src="@/global-assets/svgs/camera-disable.svg"
								alt=""
								style="margin-left: 12px"
							/>
							<!-- 筛选出的树节点 -->
							<span v-if="name.indexOf(searchValue) > -1" :style="{ color: disabled ? '#4E596A' : '' }">
								{{ name.substr(0, name.indexOf(searchValue)) }}
								<span class="font-14-bold inquire-font">{{ searchValue }}</span>
								{{ name.substr(name.indexOf(searchValue) + searchValue.length) }}
							</span>
							<!-- 普通树节点 -->
							<span v-else>{{ name }}</span>
						</div>
					</template>
				</a-tree>
			</div>
		</vue-scroll>
	</div>
</template>

<script setup lang="ts" name="DevicesTree">
import { TsSelectNode, TsTreePropsTreeData, TsTreePropsSelect } from '../../type';
import { getOnlineCount } from '@/global-utils/base.utils';
interface Tsprops {
	treeData: TsTreePropsTreeData; // tree数据
	expandedKeys?: (string | number)[];
	selectedKeys?: (string | number)[];
	searchValue?: string;
	offlineCanCheck?: boolean;
	videoPlays: string[];
}

const props = withDefaults(defineProps<Tsprops>(), {
	treeData: () => [],
	expandedKeys: () => [],
	selectedKeys: () => [],
	searchValue: '',
	offlineCanCheck: false,
	videoPlays: () => []
});

const emits = defineEmits<{
	(e: 'expand', value: (string | number)[]): void; // 点击展开收起事件
	(e: 'select', node: TsSelectNode): void; // 点击树节点事件
	(e: 'update:expandedKeys', keys: (string | number)[]): void; // 展开key
	(e: 'update:selectedKeys', keys: (string | number)[]): void; // 选中
}>();

const autoExpandParent = ref<boolean>(false); // 是否自动展开父节点
// 展开指定的树节点
const cExpandedKeys = computed({
	get() {
		return props.expandedKeys;
	},
	set(val) {
		emits('update:expandedKeys', val);
	}
});
// 处理树数据
const treeData = computed(() => {
	return props.treeData;
});
const searchValue = computed((): string => {
	return props.searchValue;
});

// 选中
const selectedKeys = computed({
	get() {
		return props.selectedKeys;
	},
	set(val) {
		emits('update:selectedKeys', val);
	}
});

// 拍平tree数据
const dataList: TsTreePropsTreeData = []; // 拍平后的数组
const flatObj: Record<string, any> = {};
const generateList = (data: TsTreePropsTreeData = [], expandIdsPath: (string | number)[]): void => {
	for (let i = 0; i < data.length; i++) {
		const node = data[i];
		const key = node.id;
		node.expandPath = node.parentId === '0' ? [node.id] : [...expandIdsPath, node.id];
		dataList.push({ key, name: node.name });
		flatObj[node.id] = node;
		if (node.children) {
			generateList(node.children, node.expandPath);
		}
	}
};

// 遍历查找是否符合的key
const getParentKey = (key: string | number, tree: TsTreePropsTreeData = []): string | number | undefined => {
	let parentKey;
	for (let i = 0; i < tree.length; i++) {
		const node = tree[i];

		if (node.children) {
			if (node.children.some((item) => item.id === key)) {
				parentKey = node.id;
			} else if (getParentKey(key, node.children)) {
				parentKey = getParentKey(key, node.children);
			}
		}
	}
	return parentKey;
};

// 点击展开收起事件
const OnExpand = (keys: (string | number)[]): void => {
	cExpandedKeys.value = keys; // 当前展开节点
	autoExpandParent.value = false; // 不自动打开父亲节点
	emits('expand', keys);
};

// 点击树节点
const Select: TsTreePropsSelect = (keys, node) => {
	console.log('keys', keys);

	emits('select', node.node);
};
let expandArr: Array<any> = [];

// 监听搜索框值
const watchStop = watch(
	searchValue,
	(value) => {
		if (value.length > 0) {
			const expanded = dataList
				.map((item) => {
					if (item.name.indexOf(value) > -1) {
						return getParentKey(item.key, props.treeData);
					}
					return null;
				})
				.filter((item, i, self) => {
					return item && self.indexOf(item) === i;
				});
			cExpandedKeys.value = expanded as (string | number)[];
			autoExpandParent.value = true;
		}
	},
	{
		deep: true
	}
);

const changeExpanded = (playIds: Array<string>): void => {
	generateList(props.treeData, []);
	if (playIds.length > 0) {
		playIds.forEach((ele: any) => {
			let newArr = flatObj[ele].expandPath;
			newArr.pop();
			expandArr = expandArr.concat(newArr);
		});
	}
	cExpandedKeys.value = [...new Set(expandArr)];
	emits('expand', cExpandedKeys.value);
};

// 计算设备总数
const cDeviceTotal = computed(() => {
	return (tree: any) => {
		return getOnlineCount(tree, 'type');
	};
});

// 计算设备在线数量
const cDeviceOnline = computed(() => {
	return (tree: any) => {
		return getOnlineCount(tree, 'disabled');
	};
});
// // 统计在线/全部个数
// const getOnlineCount = (tree: TsTreePropsTreeData = [], key: string, count = 0) => {
// 	if (tree[0].type === 0) {
// 		const subCount = tree.reduce((pre: number, cru: any) => pre + (!!cru[key] ? 0 : 1), 0);
// 		count += subCount;
// 	}
// 	for (let i = 0; i < tree.length; i++) {
// 		const node = tree[i];
// 		if (node.children) {
// 			count = getOnlineCount(node.children, key, count);
// 		}
// 	}
// 	return count;
// };
onMounted(() => {
	generateList(props.treeData, []);
	if (props.expandedKeys.length > 0) {
		props.expandedKeys.forEach((ele: any) => {
			let newArr = flatObj[ele].expandPath;
			newArr.pop();
			expandArr = expandArr.concat(newArr);
		});
	}
	cExpandedKeys.value = [...new Set(expandArr)];
});
onUnmounted(() => {
	watchStop();
});
defineExpose({
	changeExpanded,
	flatObj
});
</script>

<style lang="less">
.real-video-devices-tree {
	position: relative;
	width: 100%;
	height: calc(100% - 105px);
	padding: 0 1px 0 8px;

	.device-num {
		color: @text03;
	}

	.ant-tree .ant-tree-switcher {
		width: 100% !important;
	}

	.inquire-font {
		color: @primary02;
	}

	.title {
		width: 100%;
		margin-top: -2px;
		border-radius: 6px;
		font-size: 12px;
		font-weight: 400;
		white-space: nowrap;
		color: @text01;

		&:hover {
			background-color: @mask03;
		}

		img {
			margin-right: 6px;
		}
	}

	.device-title {
		position: relative;
		display: flex;
		width: calc(100% - 16px);
		padding: 8px 12px 8px 16px;
		font-size: 14px;
		font-weight: 400;
		color: @text03;
		align-items: center;

		&--offline {
			&::after {
				position: absolute;
				top: 6px;
				left: 6px;
				width: 8px;
				height: 8px;
				border-radius: 50%;
				background: #f59700;
				content: '';
			}
		}
	}

	.device-title-active {
		background-color: @mask04;
	}

	.ant-tree {
		color: @text03;
		background: transparent;

		.ant-tree-indent {
			display: none;
		}

		.ant-tree-treenode {
			width: 100%;
			margin-bottom: 8px;
			border-radius: 6px;

			.title-top {
				display: flex;
				justify-content: space-between;
				width: 220px;
			}
		}

		.ant-tree-treenode-leaf-last {
			margin-bottom: 12px;
		}

		.ant-tree-node-selected {
			background: transparent !important;
		}
	}

	.ant-tree-switcher-noop {
		display: none;
	}
}

.alarmStatus {
	position: absolute;
	left: 10px;

	&::after {
		position: absolute;
		top: 14px;
		right: 12px;
		width: 8px;
		height: 8px;
		border-radius: 50%;
		background: #f59700;
		content: '';
	}
}
</style>
